#include "thread.h"

Thread::Thread()
    : m_hThread( 0 )
{

}

Thread::~Thread()
{

}

void Thread::Start( IThreadCallback* pCallback, void * lpParam )
{
    AutoLocker_( m_locker );
    if( !m_hThread )
    {
        ThreadParam *pParam = new ThreadParam;
        if( pParam )
        {
            pParam->pThis = this;
            pParam->lpParam = lpParam;
            pParam->pCallback = pCallback;

            m_hThread = (HANDLE)::_beginthreadex( 0, 0, Run, (void*)pParam, 0, 0 );
        }
    }
}

void Thread::Stop( DWORD nTimeout )
{
    m_locker.Lock();
    if( m_hThread )
    {
        m_locker.Unlock();
        ::WaitForSingleObject( m_hThread, nTimeout );

        AutoLocker_( m_locker );
        if( m_hThread )
        {
            ::TerminateThread( m_hThread, 0 );
            ::CloseHandle( m_hThread );
            m_hThread = 0;
        }
    }
    else
        m_locker.Unlock();
}

BOOL Thread::IsRun()
{
    AutoLocker_( m_locker );
    return ( m_hThread != 0 );
}

unsigned int __stdcall Thread::Run( void * lpParam )
{
    ThreadParam    *pParam = (ThreadParam*)lpParam;
    if( pParam )
    {
        Thread * pThis = pParam->pThis;
        IThreadCallback * pCallback = pParam->pCallback;
        if( pThis )
        {
            pThis->RunCallback( pCallback, pParam->lpParam );
        }
        delete pParam;
    }

    return 0;
}

void Thread::RunCallback( IThreadCallback * pCallback, void * lpParam )
{
    if( pCallback )
    {
        pCallback->OnThread( this, lpParam );
    }

    AutoLocker_( m_locker );
    ::CloseHandle( m_hThread );
    m_hThread = 0;
}